Assembly Language
©
Copyright Brian Brown, 1988-2000. All rights reserved.
| Notes | Home Page |
ASSEMBLY LANGUAGE PROGRAMMING, Part 2
ASSEMBLER DIRECTIVES
As mentioned previously, assembler directives
are instructions to the assembler, and are not translated into machine
instructions. The use of directives gives the programmer some control over the
operation of the assembler, increasing flexibility in the way programs are
written. The following is a list of the common pseudo-ops.
name: EQU expression
Consider the following statement.
NUMBER1: EQU 36H
The assembler will replace every occurrence of the label NUMBER1 with the value its been equated to, ie, 36 hexadecimal. The statement
LDAA #NUMBER1
will be interpreted by the assembler as
LDAA #36H
An absolute symbol represents a 16bit value; an alias is a name that represents another symbol. The declared name must be unique, one that has not been previously declared. The redefining of a previous symbol is normally not allowed.
NUM1: EQU 20H
... ...
NUM1: EQU 30H ; error
ORG 120H
LDAA #FFH
The statement LDAA #FFH begins at byte 120h.
ORG $ + 2
start: LDAA #34H
The instruction associated with the label start is declared to start at the address 2bytes beyond the current value of the location counter (specified by $).
CPU cpuname
where cpuname consists of a valid processor name, eg
CPU 6802
This directive appears before any machine instructions.
HOF recordtype
where recordtype is one of the following
MOT ; motorola formats
INT ; intel formats
TEK ; tektronix
formats
This directive appears before any machine instructions.
DFB definebyte
Its format is,
name: DFB initialvalue,,,
The name portion is optional. Consider the following examples for CRS8.
value1: DFB 16
form: DFB 6*2
text: DFB "Enter your name: "
In the first example, the label value1 is assigned a single byte of storage, which is initialized to 16 decimal.The second example allocates a single byte of storage for the label form, and initializes it equal to 12. The last example allocates 17 bytes of storage for the label text. The first byte will be initialized to E, whilst the last byte is initialized to an ASCII space.
DWM define word, most significant byte first
DWL define word, least
significant byte first
Its format is,
name: DWM initialvalue,,,
The name portion is optional.
DWM 1687H
mess: DWM 'ab'
The first example allocates one word of storage, having the values 16H followed by 87H. The second example defines mess as a word initialized with the character values a followed by b. The b will be placed in the low-order byte, and the a will be placed in the high order byte. If only one character is specified, the high-order byte will contain 0.
Strings when using the DW directive must not contain more than two characters.
array: DFS 100
This example allocates 100 storage bytes, associating the first byte with the label array. The value of these bytes is indeterminate at this point. The 100 bytes will be allocated relative to the current location counter.
END
In this example, the END directive informs the assembler that there is no more source statements.
ORG 0100H
start: LDAA #3FH
JMP start
END start
In this example, the END directive also specifies that the entry point to the program is the label start, whose address is 0100H.
SAMPLE PROGRAM FOR MC6802 USING CRS8
The following source file has
been named MC6802.ASM
CPU 6802 ; 6802 processor HOF MOT ; Motorola Records ORG 0100H ; Start of Data Source: DFB 'Hello and Welcome' Length: EQU $ - Source ;Length of Source Destin: DFS Length ; Buffer which has same ; length as Source ORG 0120H ; Start of Code Entry: LDX #Source ; Point Index Reg to ; Source string LDAB #Length ; Number of characters to move Loop: LDAA 0,X STAA Length,X INX DECB BNE Loop Fin: JMP Fin END Entry
This program is assembled by typing the following command
CRS8 MC6802
It is not necessary to type the extension .ASM, and CRS8 will produce two output files.
MC6802.PRN ; a list file showing the code generated MC6802.HEX ; the record file for downloading to the ; target system or Eprom programmer
The listing file MC6802.PRN looks like
C:6802.TBL CPU 6802 ; 6802 processor C:6802.HEX HOF MOT ; Motorola Records 0100 ORG 0100H ; Start of Data 0100 48656C6C6F Source: DFB 'Hello and Welcome' 0011 = Length: EQU $ - Source ; Length of Source 0111 Destin: DFS Length ; Buffer which has same ; length as Source 0120 ORG 0120H ; Start of Code 0120 CE0100 Entry: LDX #Source ; Point Index Reg to ; Source string 0123 C611 LDAB #Length ; Number of characters ; to move 0125 A600 Loop: LDAA 0,X 0127 A711 STAA Length,X 0129 08 INX 012A 5A DECB 012B 26F8 BNE Loop 012D 7E012D Fin: JMP Fin 0130 END Entry
The first column is the address, the second the instructions or data, and then the mnemonics and comments. This listing is used by the programmer to verify that the assembler has produced the correct instructions and data at the correct addresses. We can clearly see that it has correctly interpreted the address of Source in the statement LDX #Source as the bytes CE 0100.
The record format file MC6802.HEX looks like
S00D0000433A363830322E48455892 S113010048656C6C6F20616E642057656C636F6D1D S10401106585 S1130120CE0100C611A600A711085A26F87E012D9F S9030120DB
The format of a motorola record is
Digit 0,1 Record Type = S0, S1 or S9 2,3 Number of bytes in Record which includes the load address and checksum bytes 4,5,6,7 Load Address 8 to n-2 Data or coded instructions n-1 to n Checksum value The S0 record identifies the program name The S1 record identifies the data and coded instructions The S9 record identifies the program entry point eg S1 04 0110 65 85 ^ ^ ^ ^ ^checksum ^ ^ ^ ^ data ^ ^ ^ load address ^ ^ number of bytes in record ^ record type
The file is then downloaded to the target system.
ELEMENTARY DATA TYPES
Most programming languages support data types
like characters and integers. At the processor level, some instructions support
integer type operations such as multiply or divide (except 6802).The programmer
is responsible for keeping track of data types. The processor treats all data
the same, and if the program goes astray, can interpret data as instructions and
vise versa.
Lets look at how elementary data is represented by the programmer for use in assembly language programs.
Letter: DFB 'A'
associates one byte of storage to the variable Letter, initializing it to the ASCII character 'A' (41H).
String: DFB 'Hello there.'
allocates 12 bytes of storage space. The variable String has the address of the first byte, which has been allocated the character 'H' (48H).
Number1: DWM -17D
allocates a word of storage for the variable Number1, initializing the word to -17 decimal. Some processors have different instructions for operations on signed and unsigned integers. If the processor cannot handle a 16bit value (ie, has only eight bit registers), software will need to be written to do any comparisons on these types.
Digits: DFS 10
allocates 10 locations for a character based array called Digits. The following code routine initializes the Digits array (each successive element) to the digits 0 to 9.
ORG 0120H start: LDAA #30H ; ASCII '0' LDAB #11 ; ten digits LDX #Digits loop: STAA 0,X INX ; next element INCA ; next digit DECB BNE loop exit: ....
Typical Array Operations
The following routines are typical of
functions which are performed on character based arrays.
CPU 6802 HOF MOT ORG 100H str1: DFS 10 st1len: EQU $ - str1 str2: DFS 10 ORG 120 HSRCINX:DFS 02H ; pointer for src string DSTINX: DFS 02H ; pointer for dest string start: LDX #str1 ; store address of str1 STX SRCINX LDX #str2 ; store address of str2 STX DSTINX jsr initstr1 ; initialise str1 jsr copystr ; copy str1 to str2 exit: bra exit initstr1: LDAA #41H ; character 'A' LDAB #11 ; elements 1 - 30 LDX #str1 ; point to str1 lp1: STAA 0,X ; store character INX ; next element INCA ; next value DECB ; loop around BNE lp1 LDAA #00 ; null terminator STAA 0,X RTS copystr: LDX SRCINX ; pick up source pointer cplp2: LDAA 0,X ; get source character CMPA #00H ; eostr? BEQ cpstrq ; yes, then exit INX ; else inc source pointer STX SRCINX ; store source ptr LDX DSTINX ; get destination pointer STAA 0,X ; store character INX ; inc dest ptr STX DSTINX ; store dest ptr LDX SRCINX ; reload source pointer BRA cplp2 ; repeat cpstrq: LDX DSTINX ; Null terminate dest str CLR 00,X RTS END start1
CPU 6802 HOF MOT EOFSTR: EQU 00H ORG 100H str1: DFB 'Hello and Welcome.', 00H ORG 120H start: LDX #str1 ; point to string jsr strlen ; find length of str1 exit: bra exit strlen: LDAB #00 ; character count strlp1: LDAA 0,X ; read character CMPA #EOFSTR ; is it end of string BEQ strexit ; yes, then exit INX ; no, inc str ptr INCB ; inc character count BRA strlp1 ; and repeatstr exit: RTS ; acc B has length END start2
CPU 6802 HOF MOT EOFSTR: EQU 00H ORG 100H str1: DFB 'Hello and Welcome.', 00H ORG 120H start: LDAA #6FH ; ASCII 'o' LDX #str1 ; point to src string jsr strpos ; find first 'o' in str1 exit: bra exit strpos: CMPA 0,X ; is char = search value BEQ strex2 ; yes then exit CMPA #EOFSTR ; is it end of string BEQ strex1 ; yes, then exit INX ; no, inc str ptr BRA strpos ; and repeat strex1: LDX #0000H ; not found strex2: RTS ; Index reg has address END start3
ARRAY INDEX CALCULATIONS
This refers to calculating the address of
a specified element within an array. In single dimensioned arrays, this is
equivalent to
BASE_ADDRESS + (ELEMENT_NUMBER * NUMBER_OF_BYTES_PER_ELEMENT)
In multi-dimensioned arrays, this is equivalent to
BASE_ADDRESS + (Col_Num + (Row_num * Num_Col_per_row)) * Num_Bytes_per_Element)